"""
人员检测相关的数据模型定义
"""
from datetime import datetime
from typing import Optional, List, Dict, Any, Tuple
from dataclasses import dataclass, field
from enum import Enum


class DetectionStatus(str, Enum):
    """检测状态枚举"""
    PENDING = "pending"
    PROCESSING = "processing"
    COMPLETED = "completed"
    FAILED = "failed"


class AlertLevel(str, Enum):
    """告警级别枚举"""
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    CRITICAL = "critical"


@dataclass
class PersonBoundingBox:
    """人员边界框模型"""
    x1: float
    y1: float
    x2: float
    y2: float
    confidence: float
    
    def get_center(self) -> Tuple[float, float]:
        """获取中心点坐标"""
        return ((self.x1 + self.x2) / 2, (self.y1 + self.y2) / 2)
    
    def get_area(self) -> float:
        """获取边界框面积"""
        return (self.x2 - self.x1) * (self.y2 - self.y1)
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            'x1': self.x1,
            'y1': self.y1,
            'x2': self.x2,
            'y2': self.y2,
            'confidence': self.confidence
        }


@dataclass
class PersonInfo:
    """人员信息模型"""
    person_id: str
    bbox: PersonBoundingBox
    center: Tuple[float, float] = field(init=False)
    tracking_id: Optional[str] = None
    features: Optional[Dict[str, Any]] = None
    
    def __post_init__(self):
        self.center = self.bbox.get_center()
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            'person_id': self.person_id,
            'bbox': self.bbox.to_dict(),
            'center': list(self.center),
            'tracking_id': self.tracking_id,
            'features': self.features
        }


@dataclass
class PersonDetectionResult:
    """人员检测结果模型"""
    detection_id: str
    camera_id: str
    timestamp: datetime
    frame_id: Optional[str] = None
    persons: List[PersonInfo] = field(default_factory=list)
    total_count: int = 0
    confidence_threshold: float = 0.5
    processing_time: Optional[float] = None
    
    def __post_init__(self):
        self.total_count = len(self.persons)
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            'detection_id': self.detection_id,
            'camera_id': self.camera_id,
            'timestamp': self.timestamp.isoformat(),
            'frame_id': self.frame_id,
            'persons': [person.to_dict() for person in self.persons],
            'total_count': self.total_count,
            'confidence_threshold': self.confidence_threshold,
            'processing_time': self.processing_time
        }


@dataclass
class DensityAnalysisResult:
    """密度分析结果模型"""
    analysis_id: str
    camera_id: str
    timestamp: datetime
    total_persons: int
    density_score: float
    density_level: str
    regions: List[Dict[str, Any]] = field(default_factory=list)
    hotspots: List[Dict[str, Any]] = field(default_factory=list)
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            'analysis_id': self.analysis_id,
            'camera_id': self.camera_id,
            'timestamp': self.timestamp.isoformat(),
            'total_persons': self.total_persons,
            'density_score': self.density_score,
            'density_level': self.density_level,
            'regions': self.regions,
            'hotspots': self.hotspots
        }


@dataclass
class CrowdAlert:
    """人群告警模型"""
    alert_id: str
    camera_id: str
    alert_type: str
    alert_level: AlertLevel
    timestamp: datetime
    person_count: int
    density_score: float
    location: Optional[Dict[str, Any]] = None
    description: str = ""
    resolved: bool = False
    resolved_at: Optional[datetime] = None
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            'alert_id': self.alert_id,
            'camera_id': self.camera_id,
            'alert_type': self.alert_type,
            'alert_level': self.alert_level.value,
            'timestamp': self.timestamp.isoformat(),
            'person_count': self.person_count,
            'density_score': self.density_score,
            'location': self.location,
            'description': self.description,
            'resolved': self.resolved,
            'resolved_at': self.resolved_at.isoformat() if self.resolved_at else None
        }


@dataclass
class DetectionConfig:
    """检测配置模型"""
    confidence_threshold: float = 0.5
    nms_threshold: float = 0.4
    max_detections: int = 100
    input_size: Tuple[int, int] = (640, 640)
    enable_tracking: bool = True
    tracking_max_age: int = 30
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            'confidence_threshold': self.confidence_threshold,
            'nms_threshold': self.nms_threshold,
            'max_detections': self.max_detections,
            'input_size': list(self.input_size),
            'enable_tracking': self.enable_tracking,
            'tracking_max_age': self.tracking_max_age
        }


@dataclass
class DensityConfig:
    """密度分析配置模型"""
    grid_size: Tuple[int, int] = (10, 10)
    density_threshold: float = 0.1
    alert_threshold: float = 0.8
    smoothing_factor: float = 0.3
    hotspot_radius: int = 50
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            'grid_size': list(self.grid_size),
            'density_threshold': self.density_threshold,
            'alert_threshold': self.alert_threshold,
            'smoothing_factor': self.smoothing_factor,
            'hotspot_radius': self.hotspot_radius
        }


@dataclass
class DetectionTask:
    """检测任务模型"""
    task_id: str
    camera_id: str
    task_type: str
    status: DetectionStatus = DetectionStatus.PENDING
    config: Optional[DetectionConfig] = None
    created_at: Optional[datetime] = None
    started_at: Optional[datetime] = None
    completed_at: Optional[datetime] = None
    progress: float = 0.0
    error_message: Optional[str] = None
    results: Optional[List[PersonDetectionResult]] = None
    
    def __post_init__(self):
        if self.created_at is None:
            self.created_at = datetime.now()
        if self.config is None:
            self.config = DetectionConfig()
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            'task_id': self.task_id,
            'camera_id': self.camera_id,
            'task_type': self.task_type,
            'status': self.status.value,
            'config': self.config.to_dict() if self.config else None,
            'created_at': self.created_at.isoformat() if self.created_at else None,
            'started_at': self.started_at.isoformat() if self.started_at else None,
            'completed_at': self.completed_at.isoformat() if self.completed_at else None,
            'progress': self.progress,
            'error_message': self.error_message,
            'results': [result.to_dict() for result in self.results] if self.results else None
        }


@dataclass
class ModelInfo:
    """模型信息模型"""
    model_id: str
    model_name: str
    model_type: str
    version: str
    framework: str
    input_shape: Tuple[int, int, int]
    classes: List[str]
    accuracy: Optional[float] = None
    inference_time: Optional[float] = None
    model_size: Optional[int] = None
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            'model_id': self.model_id,
            'model_name': self.model_name,
            'model_type': self.model_type,
            'version': self.version,
            'framework': self.framework,
            'input_shape': list(self.input_shape),
            'classes': self.classes,
            'accuracy': self.accuracy,
            'inference_time': self.inference_time,
            'model_size': self.model_size
        }


@dataclass
class PerformanceMetrics:
    """性能指标模型"""
    metric_id: str
    model_id: str
    timestamp: datetime
    fps: float
    inference_time: float
    preprocessing_time: float
    postprocessing_time: float
    memory_usage: float
    gpu_utilization: Optional[float] = None
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            'metric_id': self.metric_id,
            'model_id': self.model_id,
            'timestamp': self.timestamp.isoformat(),
            'fps': self.fps,
            'inference_time': self.inference_time,
            'preprocessing_time': self.preprocessing_time,
            'postprocessing_time': self.postprocessing_time,
            'memory_usage': self.memory_usage,
            'gpu_utilization': self.gpu_utilization
        }


@dataclass
class HeatmapData:
    """热力图数据模型"""
    heatmap_id: str
    camera_id: str
    timestamp: datetime
    width: int
    height: int
    grid_size: Tuple[int, int]
    data: List[List[float]]
    max_value: float
    min_value: float
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            'heatmap_id': self.heatmap_id,
            'camera_id': self.camera_id,
            'timestamp': self.timestamp.isoformat(),
            'width': self.width,
            'height': self.height,
            'grid_size': list(self.grid_size),
            'data': self.data,
            'max_value': self.max_value,
            'min_value': self.min_value
        }


@dataclass
class EvacuationRoute:
    """疏散路径模型"""
    route_id: str
    start_point: Tuple[float, float]
    end_point: Tuple[float, float]
    waypoints: List[Tuple[float, float]] = field(default_factory=list)
    distance: float = 0.0
    estimated_time: float = 0.0
    capacity: int = 100
    current_load: int = 0
    blocked: bool = False
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            'route_id': self.route_id,
            'start_point': list(self.start_point),
            'end_point': list(self.end_point),
            'waypoints': [list(point) for point in self.waypoints],
            'distance': self.distance,
            'estimated_time': self.estimated_time,
            'capacity': self.capacity,
            'current_load': self.current_load,
            'blocked': self.blocked
        }